home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
commtc2.zip
/
COMM_TC2.DOC
< prev
Wrap
Text File
|
1993-01-04
|
11KB
|
291 lines
Comm_TC2.C Ver. 1.00, RS-232 Support for the IBM PC - Documention
Author: Kevin R. Bulgrien
February, 1989
LeTourneau College
Microcomputer Services
P.O. Box 7001
Longview, TX 75607
INTRODUCTION
This utility is an answer to the many public domain serial port routines which
I have acquired in the quest for good RS-232 support under Turbo Pascal. Unlike
the others, this one works. Not only does it work, but it also allows you to
use both COM1 and COM2 at the same time. Designed to be relatively simple and
easy to use, I hope many will benefit from it.
This code works under Turbo C. While it was written for Turbo C 2.0, it will
probably also work for older versions. For functionally equivalent routines
which work under Turbo Pascal 3.0, or 4.0 and 5.0., look for COMM_TP3 or
COMM_TP4.
DISTRIBUTION POLICY
This package may be used in any application without restriction, although I do
ask that it is not distributed in a modified form unless you give credit where
credit is due. This document must always accompany the software as well. The
files which make up this package are called COMM_TC2.C and COMM_TC2.DOC.
CREDITS
Credit for this product must go to the various authors who showed me that if I
wanted something that worked, I would have to write it myself - I won't bother
to mention their names. The most credit, however, must go to the book "Systems
Software Tools" by Ted J. Biggerstaff. I was amazed to find a book that so
clearly outlined the IBM PC interrupt and serial port hardware. The world of
IBM PC technical information is a desert, and this book is a rare oasis in the
midst of it.
FEATURES
- Interrupt driven receive routine
- Easily expandable interrupt routine
- Uninstalls the interrupt handlers on abnormal program termination
- Carrier Detect monitoring for modem support
- COM1 & COM2 simultaneously supported
- Example TTY and Port Setup routines included
- Easy to use even if you don't understand how it works
- Turbo C 2.0 compatible source code
- The price tag reads "FREE"
DISCLAIMER
While the author has extensively tested the routines in this package, he will
not be held responsible for any consequence arising from the use thereof. It
is the responsibility of the user to determine whether or not the enclosed
routines will satisfactorily perform the required functions.
GETTING STARTED - DOES IT REALLY WORK?
If you want to prove that these routines really work, just run the program as
it is distributed. What you will see is a crude terminal emulation program
that is capable of receiving information from both COM ports at the same time.
The screen echoes data from the "logged" COM port and buffers the data from
the other port. When the other COM port is logged, the buffered data is sent
to the screen. Also provided is a setup routine that lets you select a baud
rate from 110 to 38400. The other protocol attributes are also selectable.
You will quickly notice that the screen I/O for the terminal emulation barely
keeps up with a 1200 baud transmission due to the slowness of the built-in
Turbo C 'putch' function. Obviously, you should find a faster method to write
character data if you are going to use the screen very much.
SETTING COMM_TC2 UP TO USE IN YOUR OWN PROGRAMS
In order to use the serial routines, you may remove all of the extra code that
is included for the TTY example routines. It is not important for you to
understand how the routines work, but the following declarations are not
optional and are required for normal RS-232 operation:
#include <dos.h>
#include <bios.h>
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 512
enum BaudType {B110,B150,B300,B600,B1200,B2400,B4800,B9600,B19200,B38400};
enum ParityType { None, Odd, Null, Even, MarkOff, Mark, SpaceOff, Space };
enum Boolean { FALSE, TRUE };
typedef unsigned char byte;
typedef unsigned int word;
typedef struct
{
word THR;
word RHR;
word DLL;
word IER;
word DLM;
word IIR;
word LCR;
word MCR;
word LSR;
word MSR; } INS8250 [2];
typedef struct
{
byte Baud;
byte Parity;
byte Stop;
byte Bits; } ComSettingsType [2];
const INS8250 RS232 = {
{ 0x3F8, 0x3F8, 0x3F8, 0x3F9, 0x3F9,
0x3FA, 0x3FB, 0x3FC, 0x3FD, 0x3FE
},
{ 0x2F8, 0x2F8, 0x2F8, 0x2F9, 0x2F9,
0x2FA, 0x2FB, 0x2FC, 0x2FD, 0x2FE
}
};
void interrupt (*OldIntVector [2]) ();
enum Boolean IntInstalled [2];
word InHead [2], InTail [2];
ComSettingsType ComSettings;
byte InBuffer [2] [MaxSize];
enum Boolean Carrier [2];
word MaxPorts;
void SetupRS232(byte Com,byte Baud,byte Parity,byte StopBits,byte DataBits)
void interrupt IntHandler ()
void InstallInt (byte Com)
void RemoveInt (byte Com)
atexit_t RemoveIntOnExit (void)
The following declarations are optional in that you can write your own routines
to actually send and receive RS-232 information in the form that you wish to
send it. They are not optional if you do not write your own replacements.
void WriteCOM (byte Com, byte *DataPtr)
byte ReadCOM (byte Com)
These routines are relevant only to the TTY emulation, but you may be able to
use them to better understand how to use the actual port routines:
void SetUpPort (byte Com)
void TTY (enum Boolean LocalEcho)
The main program MUST include the following code as it will cause the program
to safely remove the interrupt handlers no matter how the program terminates:
main ()
{
atexit ((atexit_t) RemoveIntOnExit);
IntInstalled [0] = FALSE;
IntInstalled [1] = FALSE;
/* MaxPorts provides error checking in some of the required functions */
MaxPorts = (biosequip () & 0x0E00) >> 9;
/* The rest of your program body goes here */
}
HOW TO USE THE INTERRUPT HANDLERS IN YOUR PROGRAM
Important note: Never compile interrupt handlers with the stack checking code
enabled. Doing so will cause the program to crash every time
the interrupt is invoked.
At any time you may invoke SetupRS232 to change the settings of the COM ports.
Unless you are sure the port is already set up correctly, you should invoke
SetupRS232 before you install the interrupt with InstallInt.
You may install either COM1, COM2 or both with InstallInt at any time and in
any order.
You may uninstall either COM1, COM2 or both with RemoveInt at any time and in
any order.
To read data that has come in from the port, one of the following is required:
1) byte ReadCOM (byte Com)
where Com is 0 or 1 for COM1 or COM2. If no data is available, this
routine waits until it arrives.
2) disable ();
DataReady = (InTail [CurrentCom] != InHead [CurrentCom]);
enable ();
where DataReady is a user defined enum Boolean that will be TRUE (1) if
data is waiting in the buffer or FALSE (0) if no data is waiting.
disable ();
Buffer [0] = InBuffer [CurrentCom] [InHead [CurrentCom]];
InHead [CurrentCom] = (InHead [CurrentCom] + 1) % MaxSize;
enable ();
where Buffer is a user defined pointer to an array of char that will
contain the next item in the buffer IF AND ONLY IF DateReady is TRUE.
The item is removed from the buffer with the statement following the
assignment. A null does not terminate the character received.
NEVER omit the disable() and enable() statements from these program
fragments. To do so would cause the program to operate unpredicatably.
To write data to the port, use one of the following methods:
1) void WriteCOM (byte Com, byte *DataPtr)
where Com is the 0 or 1 for COM1 or COM2 and DataPtr is a pointer to
string data to be sent to the port. This routine will pause until all of
the data has been sent. The data must end with a null character.
2) PortReady = ((inportb (RS232 [Com].LSR) & 0x20) = 0x20);
where PortReady is a user defined enum Boolean variable which will be
TRUE (1) if the port Transmitter Holding Register is ready for a
character to send to the port.
PortReady = PortReady && ((inportb (RS232 [Com].MSR) & 0x30) = 0x30);
This statement allows you to see if the CTS and DTR lines indicate that
the other serial device is ready to receive data. It may be omitted if
you do not want to check these lines.
disable ();
outportb (RS232 [Com].LCR, inportb (RS232 [Com].LCR) & 0x7F;
outportb (RS232 [Com].THR, *DataPtr);
enable ();
where DataPtr is a user defined pointer to an array of char that
contains a character to send to the port. PortReady MUST be TRUE
before placing this data in the Transmitter Holding Register otherwise
the previous data item will be lost.
NEVER omit the disable() and enable() statements from these program
fragments. To do so would cause the program to operate unpredicatably.
SUPPORT
User support may be obtained by contacting me via the LeTourneau College BBS
at (214) 237-2742. The BBS runs 24 hours a day and accepts calls at 300, 1200,
and 2400 baud. Since I am the SysOp of this board, this is the fastest way to
reach me. My GEnie mail address is K.BULGRIEN, but money being at a premium,
I do not always check in on a regular basis. I may also be reached during
business hours at (214) 753-0231 ext. 352.
Support will be limited to clarification of the routines I wrote. I will not
debug your routines or enhance my routines for your specific application.
UPDATES
I will place updates of the enclosed routines on LeTourneau College BBS at
(214) 237-2742. The BBS runs 24 hours a day and accepts calls at 300, 1200,
and 2400 baud.
I will also place updates in the BORLAND RT on the GEnie information service.
Possible updates may include:
1) An interrupt driven transmitter
2) More complete support of the Modem Status interrupt
3) Support of the Line Status interrupt
4) Support additional COM ports
5) Miscellaneous enhancements
6) Bug fixes
VERSION HISTORY
1.00 11/88 The original version placed in the Borland Roundtable on GEnie.
THE END